1 00:00:00,800 --> 00:00:01,550 Welcome back. 2 00:00:01,550 --> 00:00:06,860 In this lecture we're going to script the server script that's going to validate and handle the guns 3 00:00:06,860 --> 00:00:07,730 in our game. 4 00:00:07,730 --> 00:00:13,160 The purpose of this server script is to listen to that gun remote event and do server side effects for 5 00:00:13,160 --> 00:00:15,860 our guns, like the muzzle flash and dealing damage. 6 00:00:15,860 --> 00:00:21,200 So to get started, we'll create a new script in Server Script service and I'm going to call this my 7 00:00:21,200 --> 00:00:22,910 guns handler. 8 00:00:24,060 --> 00:00:26,730 We'll paste in that same template that we've been using. 9 00:00:27,840 --> 00:00:33,480 I'll get rid of this section and then this section, and we can go ahead and grab replicated storage 10 00:00:33,480 --> 00:00:35,280 to get access to that event. 11 00:00:36,520 --> 00:00:39,550 And we're also going to grab the player service. 12 00:00:41,980 --> 00:00:44,050 And then we can go ahead and create a couple variables. 13 00:00:44,050 --> 00:00:45,820 One for our gun comms enum. 14 00:00:45,820 --> 00:00:50,350 So we'll require for replicated storage and modules dot enums. 15 00:00:50,350 --> 00:00:51,820 We'll get our gun comms enum. 16 00:00:51,820 --> 00:00:54,370 And then we can go ahead and get our gun event. 17 00:00:54,370 --> 00:00:57,940 And that's replicated storage dot remotes dot gun event. 18 00:00:58,390 --> 00:01:00,310 Then we can go ahead and listen to this event. 19 00:01:00,310 --> 00:01:03,850 So gun event dot on server event we're going to connect. 20 00:01:04,810 --> 00:01:07,240 Get a function and will be passed the player. 21 00:01:07,270 --> 00:01:12,550 They will pass us the action we would like the server to perform as well as any additional arguments. 22 00:01:12,550 --> 00:01:13,750 We'll call args. 23 00:01:14,580 --> 00:01:19,320 Now, since this event is going to be fired when we want to either reload or shoot our gun, we want 24 00:01:19,320 --> 00:01:23,010 to make sure we stop any exploiters from messing with our remote event. 25 00:01:23,010 --> 00:01:27,990 So, for example, if the player that fired this event does not have a character model, then we're 26 00:01:27,990 --> 00:01:33,060 just going to return because how are they shooting or reloading a gun when they don't even have a character 27 00:01:33,060 --> 00:01:33,660 model? 28 00:01:33,660 --> 00:01:38,370 The next thing we need to verify is that this player is actually holding a gun in their hand. 29 00:01:38,700 --> 00:01:42,930 So make a variable, we'll call it gun, and it's going to be equal to our player's character. 30 00:01:42,930 --> 00:01:47,040 And we're going to find first child on them which is a tool. 31 00:01:48,230 --> 00:01:50,540 If we do not find such a tool. 32 00:01:50,540 --> 00:01:52,490 So if not gun. 33 00:01:53,270 --> 00:01:56,270 Or if they do have a toe on them, but it's not a gun. 34 00:01:56,270 --> 00:02:02,390 So if not gun, get attribute gun type, if it does not have the gun type attribute, then we're just 35 00:02:02,390 --> 00:02:05,870 going to return because they're not holding a tool or they don't have a gun on them. 36 00:02:05,870 --> 00:02:09,830 Otherwise, if they do have a gun on them, then we can go ahead and grab the properties for that gun 37 00:02:09,830 --> 00:02:13,190 and we'll require the gun dot properties. 38 00:02:13,580 --> 00:02:15,980 Then we can go ahead and check the action they want us to do. 39 00:02:15,980 --> 00:02:21,410 So if the action is equal to the gun comms enum dot two server for example validate shot. 40 00:02:21,590 --> 00:02:24,230 Then we'll perform the functionality for that. 41 00:02:24,230 --> 00:02:30,080 Otherwise if the action is equal to the gun comms enum dot two server dot validate reload, then we'll 42 00:02:30,080 --> 00:02:31,460 perform an action for that. 43 00:02:31,460 --> 00:02:33,410 And we can go ahead and actually create two functions. 44 00:02:33,410 --> 00:02:36,500 For doing that we'll have a function called reload. 45 00:02:36,620 --> 00:02:39,830 And then we can also have a function called shoot. 46 00:02:41,620 --> 00:02:45,880 And to these functions, we could pass the player the gun. 47 00:02:45,880 --> 00:02:48,520 They're holding the properties for their gun. 48 00:02:48,610 --> 00:02:50,350 Copy that and do it for both. 49 00:02:50,350 --> 00:02:56,140 And then specifically for our shoot function, we're also going to want to get the arguments along with 50 00:02:56,140 --> 00:02:57,850 the gun and its properties. 51 00:02:57,850 --> 00:03:01,480 So for example if they hit anything what are the instances they hit. 52 00:03:01,480 --> 00:03:03,760 What position did they hit him at stuff like that. 53 00:03:04,470 --> 00:03:10,980 And then when we validate a shot, what we want to make sure of is that the arguments we're being passed 54 00:03:10,980 --> 00:03:12,000 are correct. 55 00:03:12,000 --> 00:03:18,690 So if an exploiter decides to tamper with our event and try to force the server to error or cause some 56 00:03:18,690 --> 00:03:25,110 kind of problem, we want to prevent that from happening by checking to see what this argument is, 57 00:03:25,110 --> 00:03:27,750 so we can get the type of the argument we'll call it. 58 00:03:27,780 --> 00:03:28,680 What type? 59 00:03:29,670 --> 00:03:34,080 And that's going to be equal to the type of our argument. 60 00:03:34,960 --> 00:03:39,400 If our type, let's say it's not equal to a table, which is what we expect. 61 00:03:40,000 --> 00:03:43,870 And our type is not equal to nothing. 62 00:03:43,900 --> 00:03:53,500 Then we need to just return and give out a warning saying something like incorrect data passed from 63 00:03:53,500 --> 00:03:54,490 the client. 64 00:03:54,490 --> 00:04:02,050 So client to server, because we expect that this args parameter is either going to be a table or nothing. 65 00:04:02,050 --> 00:04:06,700 So if the player hits something then this will be a table full of information. 66 00:04:06,700 --> 00:04:08,530 But if they don't hit anything then it'll be nil. 67 00:04:08,530 --> 00:04:13,990 But if it's neither a table nor a nil, then that means an exploiter is messing with this remote event. 68 00:04:13,990 --> 00:04:15,610 So we're just going to return. 69 00:04:16,150 --> 00:04:21,730 Another thing we want to check is the contents inside of our args table. 70 00:04:21,820 --> 00:04:26,140 So what we want to do is we want to check if the gun. 71 00:04:27,010 --> 00:04:33,460 Get attribute gun type is equal to standard because the standard gun or the shotgun is going to send 72 00:04:33,460 --> 00:04:36,010 us different information inside of this argument table. 73 00:04:36,010 --> 00:04:45,940 So if the attribute of the gun type is standard and let's say what type is equal to table, then what 74 00:04:45,940 --> 00:04:54,250 we need to check is we need to check if the type of inside of the arguments table, the raycast result 75 00:04:54,250 --> 00:04:54,700 key. 76 00:04:54,940 --> 00:04:57,850 If this is not also equal to a table. 77 00:04:59,910 --> 00:05:06,480 So if we have a problem there, or another problem we could have is the type of the args. 78 00:05:06,720 --> 00:05:09,120 Instance position that we also pass. 79 00:05:09,850 --> 00:05:15,790 If that is not equal to the type of vector three, then we've also encountered another issue. 80 00:05:15,910 --> 00:05:22,360 So in this instance we also want to return because yes, they sent us a table. 81 00:05:22,360 --> 00:05:26,590 But the stuff in the table does not match what we'd expect. 82 00:05:26,590 --> 00:05:30,160 So we need to return and then give another warning. 83 00:05:30,160 --> 00:05:32,800 And we can basically just give the exact same message. 84 00:05:32,800 --> 00:05:35,440 And then we could also segregate this into different ones. 85 00:05:35,440 --> 00:05:36,910 So this is the first warning. 86 00:05:36,910 --> 00:05:38,470 This is our second warning. 87 00:05:38,620 --> 00:05:44,320 Otherwise once we have verified that the information coming to the server is correct, then we can use 88 00:05:44,320 --> 00:05:50,050 our shoot function and we'll pass the player that fired this event and we'll pass their gun, the properties 89 00:05:50,050 --> 00:05:52,450 for the gun and the arguments. 90 00:05:52,960 --> 00:05:54,100 Now for reloading. 91 00:05:54,100 --> 00:05:58,990 We don't need to verify or validate any information here, because the client is not going to be sending 92 00:05:58,990 --> 00:06:02,440 us any information except for the action they would like us to perform. 93 00:06:02,440 --> 00:06:08,230 So we could just directly call our reload function, pass our player the gun they're holding and the 94 00:06:08,230 --> 00:06:09,910 properties for that gun. 95 00:06:10,480 --> 00:06:13,630 So let's go ahead and fill out our shoot function. 96 00:06:13,660 --> 00:06:18,340 The first thing we want to verify is if there's actually ammo in the magazine of the gun. 97 00:06:18,340 --> 00:06:26,230 So if the gun get attribute ammo and mag if that is equal to zero, then we're just going to return 98 00:06:26,230 --> 00:06:28,360 and not do anything because they don't have any ammo. 99 00:06:29,200 --> 00:06:33,250 Another thing we want to verify is we want to keep track here on the server. 100 00:06:33,250 --> 00:06:37,480 When's the last time the player fired this event to shoot their gun? 101 00:06:37,480 --> 00:06:43,000 And that's because an exploiter could easily bypass the cooldown that we set on the client, and rapid 102 00:06:43,000 --> 00:06:46,180 fire this remote event to shoot their gun super, super fast. 103 00:06:46,180 --> 00:06:52,570 So we also need to keep track of when the player last shot their gun here on the server as well. 104 00:06:52,570 --> 00:06:58,270 So I'll create a table and I'm going to call this table time since last shot. 105 00:06:58,420 --> 00:07:01,270 And we're going to store the players in here. 106 00:07:01,270 --> 00:07:07,660 And we're going to store each of their guns or whatever gun they use to fire this event with and check 107 00:07:07,660 --> 00:07:10,840 to see when's the last time they fired a shot. 108 00:07:11,230 --> 00:07:15,010 Of course, if this is the player's first time shooting their gun, they're not going to have anything 109 00:07:15,010 --> 00:07:16,990 inside of this table, so we need to check for that. 110 00:07:16,990 --> 00:07:22,360 So if they do not have a key inside of this table, then we'll set one up for them. 111 00:07:22,360 --> 00:07:25,150 So time since last shot player dot name. 112 00:07:25,150 --> 00:07:27,580 We'll set that equal to a table. 113 00:07:27,580 --> 00:07:31,630 And this table is going to contain the names of the different guns they have. 114 00:07:31,660 --> 00:07:34,420 Because a player could have multiple different guns. 115 00:07:34,420 --> 00:07:37,840 And we'll be just using the gun's name as the identifier. 116 00:07:38,320 --> 00:07:43,870 And since this is their first time firing the event by default, we'll set the time value equal to zero. 117 00:07:44,170 --> 00:07:50,020 Another thing we need to check is if this is a different gun they're firing and they don't have that 118 00:07:50,020 --> 00:07:53,830 gun inside of the table that's stored right here. 119 00:07:53,830 --> 00:08:01,330 So if they do not have inside of time last shot for their table, if they do not have the gun's name 120 00:08:01,330 --> 00:08:04,720 as a key inside of there, then we also need to set that up for them. 121 00:08:04,720 --> 00:08:09,670 So we could just copy this and set that equal to zero as well. 122 00:08:09,790 --> 00:08:13,630 Then we need to check if the current tick. 123 00:08:14,190 --> 00:08:15,930 Subtracted by. 124 00:08:16,910 --> 00:08:17,900 Whatever. 125 00:08:17,900 --> 00:08:20,990 They last fired this particular gun. 126 00:08:21,140 --> 00:08:29,360 If this is less than and this is where we're going to have to divide 60 by the property's fire rate. 127 00:08:31,090 --> 00:08:36,340 So if they somehow fired this gun faster than what's possible for their fire rate, then we're just 128 00:08:36,340 --> 00:08:38,650 going to return as well. 129 00:08:38,680 --> 00:08:44,350 However, there is a little bit of a delay from the information being sent from the client to the server. 130 00:08:44,350 --> 00:08:49,810 So just to account for any possible delays and just be a little bit generous to our players, we'll 131 00:08:49,810 --> 00:08:58,060 subtract this value by 0.05 just to give them a little bit of extra wiggle room in case any lag occurs. 132 00:08:58,390 --> 00:09:03,700 Otherwise, if everything checks out, then we can go ahead and update for this particular gun and set 133 00:09:03,700 --> 00:09:07,360 the time they last shot this gun equal to the current tick. 134 00:09:07,890 --> 00:09:13,140 And then we also want to make sure to deduct one bullet out of the ammo in their magazine. 135 00:09:13,140 --> 00:09:18,870 So we could do gun set attribute ammo in mag. 136 00:09:19,540 --> 00:09:20,950 And we'll get their current ammo. 137 00:09:20,950 --> 00:09:22,930 So gun get attribute. 138 00:09:23,730 --> 00:09:25,620 Ammo and a mag. 139 00:09:27,040 --> 00:09:29,200 And subtract that by one. 140 00:09:29,890 --> 00:09:35,920 And now here is where the server is going to have to check if this gun is a shotgun or if it's a standard 141 00:09:35,920 --> 00:09:41,170 gun, because if it's a shotgun, we need to check every single pellet inside of the arguments that 142 00:09:41,170 --> 00:09:42,490 are being passed to us. 143 00:09:42,490 --> 00:09:46,720 Whereas if it's a normal gun, we only have to check a single bullet. 144 00:09:47,020 --> 00:09:51,460 So if the gun get attribute gun type. 145 00:09:52,500 --> 00:09:54,210 If that's equal to spread. 146 00:09:54,210 --> 00:09:55,530 So it's a shotgun. 147 00:09:56,480 --> 00:09:58,760 Then we need to verify some other information. 148 00:09:58,760 --> 00:10:05,990 For example, if the number of elements or bullets inside of our args table is greater than the amount 149 00:10:05,990 --> 00:10:12,650 of pellets for this gun, then this could indicate that an exploiter is trying to mess with our game. 150 00:10:12,650 --> 00:10:15,050 So again, we're just going to return. 151 00:10:15,700 --> 00:10:20,830 Otherwise, if everything checks out, then we can go ahead and create a muzzle flash on the gun. 152 00:10:20,830 --> 00:10:28,030 We can play the gun sound, and then we can go and calculate the damage for each of the individual pellets. 153 00:10:28,330 --> 00:10:31,030 So let's go ahead and create a couple functions. 154 00:10:31,030 --> 00:10:38,920 One we can have to calculate the damage for a particular raycast result. 155 00:10:39,370 --> 00:10:42,880 And then we could have another one to create a muzzle flash. 156 00:10:42,880 --> 00:10:45,970 So we'll call it create muzzle flash. 157 00:10:46,600 --> 00:10:50,830 And then we also want to have a function to create a sound. 158 00:10:50,830 --> 00:10:52,450 So create. 159 00:10:53,260 --> 00:10:54,370 Sound. 160 00:10:54,370 --> 00:10:59,530 And actually what we can do for this function is just go back to our local script for our gun and copy 161 00:10:59,530 --> 00:11:04,270 exactly what we've done here, and then paste that here in our server script as well. 162 00:11:04,270 --> 00:11:08,020 We'll get past the parent and then the sound properties for that sound. 163 00:11:09,070 --> 00:11:16,000 And then for our create muzzle flash function, we'll also get past a parent to create a new point light. 164 00:11:16,000 --> 00:11:19,270 And then we'll also get past the properties for that point light. 165 00:11:19,270 --> 00:11:24,010 So if you remember in each one of our guns, let me go and pick one out by random. 166 00:11:24,010 --> 00:11:30,640 We defined muzzle flash properties for this gun such as the brightness, the color, the range and stuff 167 00:11:30,640 --> 00:11:31,330 like that. 168 00:11:31,330 --> 00:11:36,970 So we'll also want to get past the light properties for our point light. 169 00:11:36,970 --> 00:11:43,390 So this function what we'll do here is we'll create a new light will be equal to instance dot new point 170 00:11:43,390 --> 00:11:43,960 light. 171 00:11:44,200 --> 00:11:47,320 And then for every single property. 172 00:11:47,870 --> 00:11:50,600 And value inside of light properties. 173 00:11:51,110 --> 00:11:55,430 What we want to do is we want to set that property on our light. 174 00:11:57,190 --> 00:12:03,130 Then we can set the parent of our light equal to that parent, and then we'll make sure to enable the 175 00:12:03,130 --> 00:12:04,420 light as well. 176 00:12:04,780 --> 00:12:06,550 And then we'll return that light. 177 00:12:06,550 --> 00:12:10,810 So that way we can destroy it after like 0.05 seconds or something. 178 00:12:10,810 --> 00:12:14,320 So it's just a burst of light that appears in our game. 179 00:12:15,210 --> 00:12:18,660 So now what we could do is when we shoot our gun. 180 00:12:19,590 --> 00:12:25,170 We'll create a new muzzle flash, so we'll get the light from our create muzzle flash function. 181 00:12:25,410 --> 00:12:30,240 The parent is going to be the gun dot handle and then the muzzle attachment. 182 00:12:31,400 --> 00:12:37,010 And then we're going to pass the properties and it was called our muzzle flash properties. 183 00:12:37,550 --> 00:12:40,280 Then I'm going to spawn a function and a new thread. 184 00:12:40,310 --> 00:12:43,940 This function is just going to yield for a short period of time. 185 00:12:43,940 --> 00:12:46,790 We could do something like 0.15 seconds. 186 00:12:46,790 --> 00:12:48,740 You could also do task dot delay as well. 187 00:12:48,740 --> 00:12:53,060 So task dot delay you could do 0.15. 188 00:12:53,120 --> 00:12:54,050 It doesn't really matter. 189 00:12:54,050 --> 00:12:55,130 Either way works. 190 00:12:55,130 --> 00:12:57,530 So we'll do it with the delay method. 191 00:12:57,530 --> 00:13:01,460 So after waiting 0.15 seconds then we'll just destroy the light. 192 00:13:02,850 --> 00:13:09,090 And then we also want to emit a particle from the particle emitter that is inside of our gun. 193 00:13:09,090 --> 00:13:14,670 So inside each one of the muzzle attachments for our guns there is a flash particle emitter. 194 00:13:14,670 --> 00:13:19,140 So gun dot handle dot muzzle flash. 195 00:13:19,140 --> 00:13:21,270 We're going to emit one particle. 196 00:13:21,930 --> 00:13:25,380 And then we can go ahead and create the sound for the gun. 197 00:13:25,380 --> 00:13:26,550 So create sound. 198 00:13:26,550 --> 00:13:29,880 The parent is going to be our gun dot handle dot muzzle. 199 00:13:29,880 --> 00:13:34,470 And then the properties is going to be our shoot sound properties. 200 00:13:34,860 --> 00:13:36,900 Then we can play the sound. 201 00:13:36,900 --> 00:13:39,090 And then we'll wait for the sound to end. 202 00:13:39,090 --> 00:13:42,120 And when it does we're going to destroy it and clean it up. 203 00:13:43,000 --> 00:13:48,550 And then finally after we do that for the gun, we can go ahead and loop through every single one of 204 00:13:48,550 --> 00:13:52,780 those pellet results inside of our args table. 205 00:13:52,780 --> 00:13:58,570 So if you remember back on the client when we shoot our gun and it's a shotgun, when we fire to the 206 00:13:58,570 --> 00:14:04,150 server, we're passing a table containing all of these different information, such as the raycast result 207 00:14:04,150 --> 00:14:07,150 and then the position of that instance that we hit. 208 00:14:07,880 --> 00:14:12,290 So we're going to loop through every single result, if there is any, in our args table. 209 00:14:12,290 --> 00:14:17,840 And this is where we could use our calculate damage function and pass all that information to it. 210 00:14:17,840 --> 00:14:21,050 We could pass the properties of the gun. 211 00:14:21,050 --> 00:14:23,030 We'll pass the results. 212 00:14:23,330 --> 00:14:26,630 And then we'll make sure to pass the player as well to this function. 213 00:14:26,630 --> 00:14:28,280 So calculate damage. 214 00:14:28,280 --> 00:14:34,250 We will get passed the properties A results and then our player. 215 00:14:34,870 --> 00:14:40,750 Now inside of this calculate damage function, we first want to verify that this result actually has 216 00:14:40,750 --> 00:14:41,560 a value. 217 00:14:41,560 --> 00:14:46,450 So if we do not have a result from the raycast, then we don't need to calculate any damage because 218 00:14:46,450 --> 00:14:48,580 we didn't hit anything, so we'll return. 219 00:14:49,510 --> 00:14:55,660 Otherwise what we can go ahead and do is we can check to see if we hit a humanoid or a character model 220 00:14:55,660 --> 00:14:59,710 so we can get the character, and that's going to be equal to our result. 221 00:14:59,860 --> 00:15:07,780 And remember we have a key in this table called raycast result and store it inside of there is our instance. 222 00:15:07,780 --> 00:15:12,610 And then we can get the parent of our instance which should be a character model if we hit a character. 223 00:15:13,120 --> 00:15:16,870 So if we do not find a humanoid in this character. 224 00:15:16,870 --> 00:15:21,940 So if not character, find first child which is a humanoid. 225 00:15:23,060 --> 00:15:28,760 Or if this character belongs to another player, then we don't want to damage them. 226 00:15:28,760 --> 00:15:29,630 So. 227 00:15:30,200 --> 00:15:32,000 Using the player service. 228 00:15:32,000 --> 00:15:40,130 If we get player from character and pass our character variable and we actually get a player, then 229 00:15:40,130 --> 00:15:41,270 we're just going to return. 230 00:15:41,270 --> 00:15:46,280 So if we didn't hit a character or we did, but that belongs to a player, then we don't want to deal 231 00:15:46,280 --> 00:15:47,330 any damage. 232 00:15:48,640 --> 00:15:55,300 Otherwise, we can go ahead and calculate how much damage we need to do by grabbing the multiplier based 233 00:15:55,300 --> 00:16:00,220 on what limb we hit, so we can get that multiplier from our properties. 234 00:16:00,220 --> 00:16:03,700 And remember that's called our body part multipliers. 235 00:16:04,270 --> 00:16:08,440 And we're just going to index this with the name of the instance that we hit. 236 00:16:08,440 --> 00:16:12,640 So result dot raycast result dot instance. 237 00:16:12,640 --> 00:16:16,210 And we'll get the name of that instance to grab that multiplier. 238 00:16:16,750 --> 00:16:20,350 And then we can refer to that character, get its humanoid. 239 00:16:22,070 --> 00:16:25,730 And then we'll use the take damage function to deal damage to it. 240 00:16:25,730 --> 00:16:29,120 And that's going to be equal to our properties dot damage. 241 00:16:29,120 --> 00:16:32,900 And then we need to multiply that by our multiplier. 242 00:16:33,590 --> 00:16:40,010 And just in case, for some reason, if this variable right here is nil, we can put an Or here and 243 00:16:40,010 --> 00:16:42,290 pass a default value of one. 244 00:16:42,290 --> 00:16:49,100 So just in case, if we index our body part multipliers and we do not get a multiplier return, then 245 00:16:49,100 --> 00:16:50,660 the default is going to be one. 246 00:16:51,740 --> 00:16:59,030 And then if you remember with our knife when we attacked or hurt a zombie, it has that who last damaged 247 00:16:59,030 --> 00:17:00,620 object value inside of it. 248 00:17:00,620 --> 00:17:07,430 So we want to check if this character has fine first child who last damaged. 249 00:17:07,430 --> 00:17:14,240 Which means whatever we are hurting is a zombie, so we can go ahead and update the character who last 250 00:17:14,240 --> 00:17:18,680 damaged dot value and set that equal to the player. 251 00:17:19,250 --> 00:17:20,600 Okay, cool. 252 00:17:21,320 --> 00:17:24,740 So now we got this function set up and we can go ahead. 253 00:17:24,740 --> 00:17:30,770 And now listen for every single pellet inside of our shotguns. 254 00:17:30,770 --> 00:17:34,940 And then we want to check if our gun is in a shotgun. 255 00:17:34,940 --> 00:17:43,250 Well we need to check if the gun get attribute gun type is equal to the standard gun type. 256 00:17:43,250 --> 00:17:47,000 And if it is, then this makes our job a lot more easy. 257 00:17:47,150 --> 00:17:53,990 We can basically just copy this code here, paste that there, and instead what we can do is just call 258 00:17:53,990 --> 00:17:57,290 our calculate damage function without having to loop through everything. 259 00:17:57,680 --> 00:17:59,690 And then we'll pass the properties. 260 00:17:59,690 --> 00:18:02,540 We'll pass the args and we'll pass the player. 261 00:18:03,860 --> 00:18:04,460 Okay. 262 00:18:04,460 --> 00:18:11,240 So now let's actually go ahead and test whether or not we can shoot our gun and deal damage to humanoids. 263 00:18:11,240 --> 00:18:13,910 So I'm going to create a rig here. 264 00:18:14,520 --> 00:18:22,800 And I'll just duplicate this guy a couple times, and then we'll make sure to update the values of the 265 00:18:22,800 --> 00:18:26,070 guns in our starter pack, make sure they actually have ammo in their magazines. 266 00:18:26,070 --> 00:18:30,660 So I'll just put some ammo in there, and I'll put some ammo in this one. 267 00:18:30,660 --> 00:18:37,650 And now we can go and playtest our game and see if the server is properly verifying the results coming 268 00:18:37,650 --> 00:18:38,760 from our client. 269 00:18:39,790 --> 00:18:43,810 So if I hold my gun out and let's, let's actually just test shooting. 270 00:18:43,810 --> 00:18:44,710 So if I click. 271 00:18:46,440 --> 00:18:53,040 We are firing to the server, but it does appear that the server is not doing anything while we're firing 272 00:18:53,040 --> 00:18:53,850 this event. 273 00:18:53,850 --> 00:18:59,820 We aren't getting any errors, but the server might be prematurely returning for some reason. 274 00:18:59,820 --> 00:19:02,730 So let's go ahead and figure out why that is. 275 00:19:03,940 --> 00:19:09,100 And I believe the issue I found it right away is we forgot to put a Not statement here. 276 00:19:09,250 --> 00:19:15,580 So because we didn't put a not statement here, it's returning when the player is actually holding their 277 00:19:15,580 --> 00:19:17,050 gun which we don't want to happen. 278 00:19:17,050 --> 00:19:22,420 So we need to put a not statement here and return when the player is not holding a tool. 279 00:19:22,420 --> 00:19:23,440 That is a gun. 280 00:19:23,440 --> 00:19:29,620 Okay, now let's try and test this again and see if our guns are working. 281 00:19:30,190 --> 00:19:33,640 So if I pull out my gun and I click perfect. 282 00:19:33,640 --> 00:19:37,330 As you can see, the muzzle flash happened and it played the shoot sound. 283 00:19:37,330 --> 00:19:40,600 So I'll click it again and it's shooting our gun. 284 00:19:40,600 --> 00:19:46,630 And if we go and look in the workspace and we look at my player and we look at our gun, as you can 285 00:19:46,630 --> 00:19:50,560 see it is properly deducting the value from the ammo and mag attribute. 286 00:19:50,560 --> 00:19:56,020 So if I shoot again, as you can see it is deducting bullets from my ammo and magazine. 287 00:19:56,020 --> 00:19:58,630 Let's go ahead and try to shoot a character. 288 00:19:58,630 --> 00:20:04,270 So if I shoot them in their hand, as you can see, I have dealt very little damage. 289 00:20:04,270 --> 00:20:08,860 But if I shoot them in the face, as you can see, I've dealt a lot of damage. 290 00:20:08,860 --> 00:20:09,760 Very cool. 291 00:20:10,340 --> 00:20:12,140 Let's try a shotgun. 292 00:20:12,140 --> 00:20:15,260 Since there's going to be 12 pellets coming out of the shotgun. 293 00:20:15,290 --> 00:20:19,460 This should do a lot of damage if I shoot them in the middle of their chest. 294 00:20:19,460 --> 00:20:24,710 So if I click yep, just like that, they are dead. 295 00:20:24,830 --> 00:20:29,870 And if I go and shoot this guy, let me actually back up a bit and have the spread. 296 00:20:30,540 --> 00:20:33,180 Kind of be farther out. 297 00:20:33,180 --> 00:20:34,290 And then I click. 298 00:20:35,220 --> 00:20:35,820 There you go. 299 00:20:35,820 --> 00:20:37,080 My rig did not die. 300 00:20:37,080 --> 00:20:41,700 Let me back up a little bit more and click again and boom, they are dead. 301 00:20:41,700 --> 00:20:42,660 Very cool. 302 00:20:44,470 --> 00:20:48,490 And then if I keep shooting my guns, eventually I'll run out of ammo. 303 00:20:49,950 --> 00:20:51,690 Now I have no more ammo. 304 00:20:52,560 --> 00:20:59,400 And now what we need to implement is allowing the server to reload our guns when we press R on our keyboard. 305 00:21:00,180 --> 00:21:01,800 So let's go ahead and implement that. 306 00:21:03,090 --> 00:21:08,280 So inside of our reload function, what we want to go ahead and do is grab the current ammo inside of 307 00:21:08,280 --> 00:21:10,080 the magazine for this player's gun. 308 00:21:10,080 --> 00:21:12,060 So gun get attribute. 309 00:21:12,960 --> 00:21:14,820 Ammo in magazine. 310 00:21:14,820 --> 00:21:18,090 And then we also want to grab the ammo that they have in reserve. 311 00:21:18,090 --> 00:21:23,430 So ammo reserve is going to be equal to gun get attribute ammo reserve. 312 00:21:24,640 --> 00:21:31,960 Now, if the ammo in their magazine is equal to the properties of max mag ammo, then this player doesn't 313 00:21:31,960 --> 00:21:34,570 need to reload, so we're just going to return. 314 00:21:35,340 --> 00:21:43,230 If their ammo reserve is less than or equal to zero just in case, then they also can't reload because 315 00:21:43,230 --> 00:21:45,900 they don't have any ammo to reload with. 316 00:21:47,040 --> 00:21:48,030 Otherwise. 317 00:21:48,030 --> 00:21:56,010 What we need to do is we need to verify that this player actually waited through their reload duration. 318 00:21:56,010 --> 00:22:01,440 And a way we could check that is by actually listening to when they last shot their gun and comparing 319 00:22:01,440 --> 00:22:06,840 that to the current tick, because during that entire time the player is reloading, they're not going 320 00:22:06,840 --> 00:22:08,790 to be able to shoot that gun. 321 00:22:08,790 --> 00:22:14,760 So by checking to see how long it's been since they last shot, we can check to see if that matches 322 00:22:14,760 --> 00:22:18,210 up with the reload duration property we have set for the gun. 323 00:22:18,840 --> 00:22:25,680 So what I'm going to do is I'm going to copy this and paste this in here, just in case this player 324 00:22:25,680 --> 00:22:29,730 does not have any key inside of the time last shot table. 325 00:22:29,850 --> 00:22:39,180 Otherwise what we can go ahead and do is we can check if the current tick minus the time since we last 326 00:22:39,180 --> 00:22:43,170 shot, get the player's name for this particular gun. 327 00:22:43,950 --> 00:22:49,290 We can check if this is less than the property's dot reload duration. 328 00:22:49,290 --> 00:22:56,130 If it is, then that means this player has somehow reloaded or fired this event faster than the reload 329 00:22:56,130 --> 00:23:00,930 duration for their gun, which would indicate that this player is probably exploiting. 330 00:23:00,930 --> 00:23:03,570 So we're going to return and not doing anything. 331 00:23:04,220 --> 00:23:05,210 Otherwise. 332 00:23:05,210 --> 00:23:13,340 Well, we can go ahead and do is we can go ahead and calculate how much ammo we need to reload or put 333 00:23:13,340 --> 00:23:14,420 into our magazine. 334 00:23:14,420 --> 00:23:17,090 So we'll create a variable, we'll call it ammo needed. 335 00:23:17,330 --> 00:23:20,870 And we're going to set it equal to math dot minimum. 336 00:23:20,870 --> 00:23:27,470 We're going to get the properties dot max mag ammo and subtract it by the current ammo in our magazine. 337 00:23:28,640 --> 00:23:31,700 And then the second number we're going to pass is the ammo reserve. 338 00:23:31,700 --> 00:23:37,580 So this way we don't subtract more ammo than what is inside of our ammo reserve. 339 00:23:37,880 --> 00:23:41,210 And then once we do that, we can go ahead and set the attribute. 340 00:23:41,210 --> 00:23:44,960 So gun set attribute ammo in mag. 341 00:23:44,960 --> 00:23:49,820 We'll set that equal to the current ammo in our magazine plus the ammo we need. 342 00:23:50,500 --> 00:23:52,300 And then for. 343 00:23:53,880 --> 00:23:55,650 The ammo reserve. 344 00:23:55,800 --> 00:24:00,930 We can go ahead and set that equal to the ammo reserve minus the ammo. 345 00:24:00,960 --> 00:24:06,900 We need to fill into our magazine and that should be all we need to do for our reload function. 346 00:24:07,320 --> 00:24:10,170 So let's go ahead and test it out. 347 00:24:10,930 --> 00:24:12,340 Playtest our game here. 348 00:24:14,590 --> 00:24:15,610 Hit play. 349 00:24:16,560 --> 00:24:19,740 And then we'll go and shoot our guns. 350 00:24:19,740 --> 00:24:22,350 And actually, let's go ahead and see if automatic for our gun is working. 351 00:24:22,350 --> 00:24:27,150 So if I hold down my mouse button, as you can see, my gun is automatic. 352 00:24:28,890 --> 00:24:30,420 And now I've run out of ammo. 353 00:24:30,420 --> 00:24:33,060 So let me press R and reload my gun. 354 00:24:33,900 --> 00:24:36,540 And hopefully now I should be able to shoot my gun again. 355 00:24:36,810 --> 00:24:37,260 Perfect. 356 00:24:37,260 --> 00:24:43,410 Just like that, we have reloaded the gun, and if we go and look at our character and check out the 357 00:24:43,410 --> 00:24:44,280 attributes for the gun. 358 00:24:44,280 --> 00:24:47,520 As you can see it deducted 20 bullets from my ammo reserve. 359 00:24:47,520 --> 00:24:48,330 Very cool. 360 00:24:51,780 --> 00:24:57,750 Now that we have the fundamental system set up for our guns, we can continue to refine this system 361 00:24:57,750 --> 00:25:04,800 by adding further features like bullet holes, animation, and scripting the UI for our guns. 362 00:25:04,800 --> 00:25:07,110 I'll see you in the next lecture.